package gestorvideoclub;

import gestorvideoclub.enumeraciones.*;
import gestorvideoclub.jdbc.*;
import gestorvideoclub.util.*;
import java.util.*;
import java.util.ArrayList;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.management.timer.Timer;

public class Reserva {
    private int idReserva;
    private Cliente cliente;
    private Producto producto;
    private String titulo;
    private TipoProductoEnum tipoProducto;
    private Date fechaReserva;
    private Date fechaSMS;
    private boolean pendiente;//true = reserva pendiente; false = cancelado o alquielado, dependerá de la fecha de alquiler
    private Date fechaAlquiler;
    private static int maxDiaReserva;

    public Reserva(){}

    public Reserva(Cliente cliente, Producto producto, String titulo, TipoProductoEnum tipoProducto, Date fechaReserva){
        this.cliente = cliente;
        this.producto = producto;
        this.titulo = titulo;
        this.tipoProducto = tipoProducto;
        this.fechaReserva = fechaReserva;
        this.fechaSMS = new Date(0);
        this.fechaAlquiler = new Date(0);
        this.pendiente = true;
    }
    
    static{
        maxDiaReserva = 2;
    }

    public int getIdReserva(){
        return idReserva;
    }

    public void setIdReserva(int idReserva)
    {
        this.idReserva = idReserva;
    }

    public Cliente getCliente() {
        return cliente;
    }

    public void setCliente(Cliente cliente) {
        if(cliente != null && cliente instanceof Cliente){
            this.cliente = cliente;
        }
        else{
            System.out.println();
        }
    }

    public Date getFechaAlquiler() {
        return fechaAlquiler;
    }

    public void setFechaAlquiler(Date fechaAlquiler) {
        this.fechaAlquiler = fechaAlquiler;
    }

    public Date getFechaReserva() {
        return fechaReserva;
    }

    public void setFechaReserva(Date fechaReserva) {
        this.fechaReserva = fechaReserva;
    }

    public static int getMaxDiaReserva() {
        return maxDiaReserva;
    }

    public static void setMaxDiaReserva(int maxDiaReserva) {
        Reserva.maxDiaReserva = maxDiaReserva;
    }

    public boolean getPendiente() {
        return pendiente;
    }

    public void setPendiente(boolean pendiente) {
        this.pendiente = pendiente;
    }

    public Date getFechaSMS() {
        return fechaSMS;
    }

    public TipoProductoEnum getTipoProducto() {
        return tipoProducto;
    }

    public void setTipoProducto(TipoProductoEnum tipoProducto) {
        this.tipoProducto = tipoProducto;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public void setFechaSMS(Date fechaSMS) {
        this.fechaSMS = fechaSMS;
    }

    public Producto getProducto() {
        return producto;
    }

    public void setProducto(Producto producto) {
        if(producto != null && producto instanceof Producto){
            this.producto = producto;
        }
        else{
            System.out.println();
        }
    }


    @Override
    public String toString()
    {
      /*  return this.producto.getTitulo()+" reservado por "
                +this.getCliente().getNombre()+" "+this.getCliente().getApellidos()+" el día "+this.fechaReserva;
       *
       */
        DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
        DateFormat df2 = new SimpleDateFormat("dd/MM/yyyy");
        long aux = this.getFechaReserva().getTime();
        String cad = "Nombre: "+this.getTitulo().toUpperCase()+" Tipo: "+this.getTipoProducto();
        cad += "\nFecha de reserva: "+UtilFecha.fechaMostrar(this.getFechaReserva());

        
        Date d = new Date(0);
        long fechaLong = d.getTime();
        if(!this.getFechaSMS().equals(d) && !UtilFecha.fechaMostrar(this.getFechaSMS()).equals(df2.format(fechaLong))){
            aux = this.getFechaSMS().getTime();
            cad += "\nFecha de SMS: "+df2.format(aux);
        }
        
        else{
            cad += "\nFecha de SMS: Pendiente de enviar";
        }

        if(!this.getFechaAlquiler().equals(d) && !UtilFecha.fechaMostrar(this.getFechaAlquiler()).equals(df2.format(fechaLong))){
            aux = this.getFechaAlquiler().getTime();
            cad +="\nFecha de Alquiler: "+df2.format(aux);
        }
        else{
            cad +="\nFecha de Alquiler: Pendiente de alquilar";
        }

        if(this.getPendiente()){
            cad +="\nPendiente: Sí";
        }
        else{
            cad +="\nPendiente: No";
        }

        cad += "\nNúmero máximo de días de reserva: "+this.getMaxDiaReserva();

        return cad;
    }

    @Override
    public boolean equals(Object o)
    {
        if(o instanceof Reserva)
        {
            Reserva r = (Reserva)o;
            if(this.idReserva == r.idReserva && this.titulo.equals(r.titulo) 
                    && this.tipoProducto.equals(r.tipoProducto) && this.getCliente().equals(r.getCliente())
                    && this.fechaAlquiler.equals(r.fechaAlquiler) &&
                    this.fechaSMS.equals(r.fechaSMS) && this.fechaAlquiler.equals(r.fechaAlquiler))
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public int hashCode()
    {
        return 1;
    }

    /**
     * Método al que se le introducirá un producto y  comprobará algún cliente lo ha reservado
     */
    public static void comprobarReserva(Producto producto)
    {
        Reserva reserva = ReservaJDBC.obtenerReservaPorProducto(producto);
        
        if(reserva.getIdReserva() != 0){
            Cliente cliente = ClienteJDBC.obtenerClientePorId(reserva.getCliente().getId());
            reserva.setFechaSMS(new Date());
            reserva.getProducto().setId(producto.getId());
            producto.setEstado(ProductoEnum.Reservado);

            ReservaJDBC.modificarReserva(reserva);
            enviarSMS(cliente, reserva);
        }
        else{
            producto.setEstado(ProductoEnum.Disponible);
        }
        ProductoJDBC.modificarProducto(producto);

    }

    public static void enviarSMS(Cliente cliente, Reserva reserva)
    {
        System.out.println("\nYa tiene disponible "+reserva.getTitulo()+" en su videoclub.");
        System.out.println(" Estará reservada para usted hasta el "+UtilFecha.sumarDiasFecha(reserva.getFechaSMS(), reserva.getMaxDiaReserva()));
        System.out.println("\n\nSMS enviado al cliente: "+cliente.getNombre()+" "+cliente.getApellidos());
    }

    public static void altaReserva(Cliente cliente, Producto producto)
    {
        Date fechaReserva = new Date();
        //Obtenemos el id Cliente y el id de producto y creamos la reserva
        
        
        
        Reserva reserva = new Reserva(cliente,producto,producto.getTitulo(),producto.getTipo(), fechaReserva);
        //System.out.println(reserva);
        boolean salir = false;

        do{
            System.out.println("¿Desea reservar? Seleccione una opción: ");
            System.out.println("1. Sí");
            System.out.println("2. No");
            
            int op = introduceDatos.introduceEntero();
            switch(op){
                case 1:
                    ReservaJDBC.insertarReserva(reserva);
                    salir = true;
                    System.out.println("Su reserva se ha guardado correctamente");
                    break;
                case 2:
                    System.out.println("\nLa reserva no se ha guardado");
                    salir = true;
                    break;
                default:
                    System.out.println("Opción incorrecta");
            }
        }while(!salir);
    }

    /**
     * Consultaremos una reserva concreta
     */
    public void consultarReserva()
    {
        System.out.println(this);
    }

    /*
     La modificación no será posible, solo podremos dar de baja a una reserva
     */
    public void bajaReserva()
    {
        boolean salir = false;
        do{
            System.out.println("\n¿Desea cancelar la reserva? Seleccione una opción:");
            System.out.println("1. Sí");
            System.out.println("2. No");
            
            int op = introduceDatos.introduceEntero();
            switch(op){
                case 1:
                    this.setPendiente(false);
                    ReservaJDBC.modificarReserva(this);
                    salir = true;
                    break;
                case 2:
                    salir = true;
                    break;
                default:
                    System.out.println("Opción incorrecta");
            }
        }while(!salir);
    }

    //DEBERIA IR EN LA CLASE CLIENTE
    public static void reservasPendientes()
    {
        //Se accede a la base de datos para comprobar si el cliente tiene pendiente de
        //recoger un producto que ha reservado
        int opUsu = -1;
        Cliente cliente = new Cliente();
        // Selección de usuario
        do {
            System.out.print(">>> Usuario: ");
            String dni = EntradaTextoStatic.leeCadena();
            if(!UsuarioJDBC.existeUsuario(dni)){ // No existe el usuario
                System.out.println("[!] El usuario no existe.");
            }else{ 
                cliente = ClienteJDBC.obtenerClientePorDni(dni);
                System.out.println("\nLista de reservas del usuario: "+cliente.getNombre()+"\n");
                List<Reserva> listaReserva = ReservaJDBC.obtenerReserva(cliente);
                if(listaReserva.size()>0){//Si tiene alguna reserva pendiente
                    System.out.println("Los productos que tienen pendiente de alquilar son los siguientes: ");
                    Iterator it = listaReserva.iterator();
                    int i = 1;
            
                    while(it.hasNext())
                    {
                        Reserva reserva = (Reserva)it.next();
                        System.out.println(reserva);
                        System.out.println();
                    }
                    opUsu = 0;
                    //seleccionarReserva(listaReserva);
                }
                else{//En caso de no haber reservas pendientes
                    opUsu = 0;
                    System.out.println("No tienes productos reservados");
                }

            }
        }while(opUsu == -1);

    }


    /*
     * Este método dará la opción al usuario de cancelar una reserva o de alquilar el
     * producto reservado
     */
    public void seleccionarReserva(List listaReserva)
    {
        boolean seleccion = false;
        System.out.println("Seleccion un producto: ");
        int opcion = introduceDatos.introduceEntero();
        Reserva reserva = (Reserva)listaReserva.get(opcion+1);
        
        do{
            System.out.println("¿Qué desea hacer? Introduzca un número: ");
            System.out.println("1. Alquilar");
            System.out.println("2. Cancelar");
            System.out.println("3. Salir");
            int opcion2 = introduceDatos.introduceEntero();
            switch(opcion2)
            {
                case 1:
                    Alquiler alquiler = new Alquiler();
                    alquiler.alquilarProductoReservado(reserva);
                    seleccion = true;
                    break;
                case 2:
                    reserva.setPendiente(false);
                    seleccion = true;
                    //Acceder a la base de datos para cambiar el estado de pendiente
                    break;
                case 3:
                    seleccion = true;
                    break;
                default:
                    System.out.println("Opción incorrecta.");
            }
        }while(seleccion);

    }

    public static void actualizarReservas(){
        ArrayList<Reserva>listaReserva = ReservaJDBC.obtenerReservasPendiente();
        if(listaReserva.size()>0){
            System.out.println("Actualizando....\n");
            Iterator it = listaReserva.iterator();
            while(it.hasNext()){
                Reserva reserva = (Reserva)it.next();

                Date fSMS = reserva.getFechaSMS();
                Date fechaHoy = new Date();
                System.out.print("Producto: "+reserva.getTitulo()+" en "+reserva.getTipoProducto());
                System.out.print(". Fecha de envío del sms "+UtilFecha.fechaMostrar(reserva.getFechaSMS()));
                System.out.println(" Fecha actual "+UtilFecha.fechaMostrar(fechaHoy));
                int dif = UtilFecha.calculaDiferenciaFecha(fechaHoy, fSMS);

                String cad = "Diferencia de días "+dif;
                
                if(dif > 2){
                    comprobarReserva(reserva.getProducto());
                    reserva.setPendiente(false);
                    ReservaJDBC.modificarReserva(reserva);
                    cad += ". Reserva Cancelada";
                }else{
                    cad += ". Está dentro de plazo";
                }
                System.out.println(cad);
                System.out.println();
                
            }
        }
        else{
            System.out.println("[!] No existen reservas pendiente de actualizar");
        }
    }
}
